home *** CD-ROM | disk | FTP | other *** search
/ AM/FM: Amiga Musicians' Freeware Magazine 2 / AM-FM 2.adf / Utilities / MFT / midifile.c < prev    next >
C/C++ Source or Header  |  1991-09-21  |  10KB  |  535 lines

  1.  
  2. /*
  3.  * Read a Standard MIDI File.  Externally-assigned function pointers are
  4.  * called upon recognizing things in the file.  See midifile(3).
  5.  */
  6.  
  7. #include "midi.h"
  8. #include "midifile.h"
  9.  
  10. #define EOF (-1)
  11. #define NOARGS VOID
  12. #define VOID void
  13.  
  14. /* public stuff */
  15.  
  16. /* Functions to be called while processing the MIDI file. */
  17. VOID (*Mf_starttrack)(NOARGS) = 0;
  18. VOID (*Mf_endtrack)(NOARGS) = 0;
  19. int (*Mf_getc)(NOARGS) = 0;
  20. VOID (*Mf_eot)(NOARGS) = 0;
  21.  
  22.  
  23. VOID (*Mf_error)(char *) = 0;
  24. VOID (*Mf_header)(int,int,int) = 0;
  25. VOID (*Mf_on)(int,int,int) = 0;
  26. VOID (*Mf_off)(int,int,int) = 0;
  27. VOID (*Mf_pressure)(int,int,int) = 0;
  28. VOID (*Mf_controller)(int,int,int) = 0;
  29. VOID (*Mf_pitchbend)(int,int,int) = 0;
  30. VOID (*Mf_program)(int,int) = 0;
  31. VOID (*Mf_chanpressure)(int,int) = 0;
  32. VOID (*Mf_sysex)(int,char*) = 0;
  33. VOID (*Mf_arbitrary)(int,char*) = 0;
  34. VOID (*Mf_metamisc)(int,int,char*) = 0;
  35. VOID (*Mf_seqnum)(int) = 0;
  36. VOID (*Mf_smpte)(int,int,int,int,int) = 0;
  37. VOID (*Mf_timesig)(int,int,int,int) = 0;
  38. VOID (*Mf_tempo)(int) = 0;
  39. VOID (*Mf_keysig)(int,int) = 0;
  40. VOID (*Mf_sqspecific)(int,char*) = 0;
  41. VOID (*Mf_text)(int,int,char*) = 0;
  42.  
  43. int Mf_nomerge = 0;        /* 1 => continue'ed system exclusives are */
  44.                 /* not collapsed. */
  45. long Mf_currtime = 0L;        /* current time in delta-time units */
  46. int Mf_skipinit = 0;        /* 1 if initial garbage should be skipped */
  47.  
  48. /* private stuff */
  49.  
  50. static long Mf_toberead = 0L;
  51.  
  52. static long readvarinum(NOARGS);
  53. static long read32bit(NOARGS);
  54. static int read16bit(NOARGS);
  55. static VOID msgenlarge(NOARGS);
  56. static char *msg(NOARGS);
  57. static int readheader(NOARGS);
  58. static VOID readtrack(NOARGS);
  59. static VOID sysex(NOARGS), msginit(NOARGS);
  60. static int egetc(NOARGS);
  61. static int msgleng(NOARGS);
  62.  
  63. static int readmt(char*,int);
  64. static long to32bit(int,int,int,int);
  65. static int to16bit(int,int);
  66. static VOID mferror(char *);
  67. static VOID badbyte(int);
  68. static VOID metaevent(int);
  69. static VOID msgadd(int);
  70. static VOID chanmessage(int,int,int);
  71.  
  72.  
  73. /*----- midifile -----*/
  74.  
  75. VOID midifile()         /* The only non-static function in this file. */
  76. {
  77.     int ntrks;
  78.  
  79.     if ( Mf_getc == 0 )
  80.         mferror("midifile() called without setting Mf_getc"); 
  81.  
  82.     ntrks = readheader();
  83.     if ( ntrks <= 0 )
  84.         mferror("No tracks!");
  85.     while ( ntrks-- > 0 )
  86.         readtrack();
  87. }
  88.  
  89. static int
  90. readmt(s,skip)        /* read through the "MThd" or "MTrk" header string */
  91. char *s;
  92. int skip;        /* if 1, we attempt to skip initial garbage */
  93. {
  94.     int nread = 0;
  95.     char b[4];
  96.     char buff[32];
  97.     int c;
  98.     char *errmsg = "expecting ";
  99. retry:
  100.     while ( nread<4 ) {
  101.         c = (*Mf_getc)();
  102.         if ( c == EOF ) {
  103.             errmsg = "EOF while expecting ";
  104.             goto err;
  105.         }
  106.         b[nread++] = c;
  107.     }
  108.     /* See if we found the 4 characters we're looking for */
  109.     if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] )
  110.         return(0);
  111.     if ( skip ) {
  112.         /* If we are supposed to skip initial garbage, */
  113.         /* try again with the next character. */
  114.         b[0]=b[1];
  115.         b[1]=b[2];
  116.         b[2]=b[3];
  117.         nread = 3;
  118.         goto retry;
  119.     }
  120.     err:
  121.     (VOID) strcpy(buff,errmsg);
  122.     (VOID) strcat(buff,s);
  123.     mferror(buff);
  124.     return(0);
  125. }
  126.  
  127. static int
  128. egetc()    /* to read a single character and abort on EOF */
  129. {
  130.     int c = (*Mf_getc)();
  131.  
  132.     if ( c == EOF )
  133.         error("premature EOF");
  134.     Mf_toberead--;
  135.     return(c);
  136. }
  137.  
  138. static int
  139. readheader()        /* read a header chunk */
  140. {
  141.     int format, ntrks, division;
  142.  
  143.     if ( readmt("MThd",Mf_skipinit) == EOF )
  144.         return(0);
  145.  
  146.     Mf_toberead = read32bit();
  147.     format = read16bit();
  148.     ntrks = read16bit();
  149.     division = read16bit();
  150.  
  151.     if ( Mf_header )
  152.         (*Mf_header)(format,ntrks,division);
  153.  
  154.     /* flush any extra stuff, in case the length of header is not 6 */
  155.     while ( Mf_toberead > 0 )
  156.         (VOID) egetc();
  157.     return(ntrks);
  158. }
  159.  
  160. static VOID
  161. readtrack()         /* read a track chunk */
  162. {
  163.     /* This array is indexed by the high half of a status byte.  It's */
  164.     /* value is either the number of bytes needed (1 or 2) for a channel */
  165.     /* message, or 0 (meaning it's not  a channel message). */
  166.     static int chantype[] = {
  167.         0, 0, 0, 0, 0, 0, 0, 0,        /* 0x00 through 0x70 */
  168.         2, 2, 2, 2, 1, 1, 2, 0        /* 0x80 through 0xf0 */
  169.     };
  170.     long lookfor, lng;
  171.     int c, c1, type;
  172.     int sysexcontinue = 0;    /* 1 if last message was an unfinished sysex */
  173.     int running = 0;    /* 1 when running status used */
  174.     int status = 0;        /* (possibly running) status byte */
  175.     int needed;
  176.  
  177.     if ( readmt("MTrk",0) == EOF )
  178.         return;
  179.  
  180.     Mf_toberead = read32bit();
  181.     Mf_currtime = 0;
  182.  
  183.     if ( Mf_starttrack )
  184.         (*Mf_starttrack)();
  185.  
  186.     while ( Mf_toberead > 0 ) {
  187.  
  188.         Mf_currtime += readvarinum();    /* delta time */
  189.  
  190.         c = egetc();
  191.  
  192.         if ( sysexcontinue && c != 0xf7 )
  193.             mferror("didn't find expected continuation of a sysex");
  194.  
  195.         if ( (c & 0x80) == 0 ) {     /* running status? */
  196.             if ( status == 0 )
  197.                 mferror("unexpected running status");
  198.             running = 1;
  199.         }
  200.         else {
  201.             status = c;
  202.             running = 0;
  203.         }
  204.  
  205.         needed = chantype[ (status>>4) & 0xf ];
  206.         if ( needed ) {        /* ie. is it a channel message? */
  207.  
  208.             if ( running )
  209.                 c1 = c;
  210.             else
  211.                 c1 = egetc() & 0x7f;
  212.  
  213.              /* The &0x7f here may seem unnecessary, but I've seen */
  214.              /* 'bad' midi files that had, some, volume bytes */
  215.              /* with the upper bit set.  This code should not harm */
  216.              /* proper data. */
  217.  
  218.             chanmessage( status, c1, (needed>1) ? (egetc()&0x7f) : 0 );
  219.             continue;
  220.         }
  221.  
  222.         switch ( c ) {
  223.  
  224.         case 0xff:            /* meta event */
  225.  
  226.             type = egetc();
  227.             /* watch out - Don't combine the next 2 statements */
  228.             lng = readvarinum();
  229.             lookfor = Mf_toberead - lng;
  230.             msginit();
  231.  
  232.             while ( Mf_toberead > lookfor )
  233.                 msgadd(egetc());
  234.  
  235.             metaevent(type);
  236.             break;
  237.  
  238.         case 0xf0:        /* start of system exclusive */
  239.  
  240.             /* watch out - Don't combine the next 2 statements */
  241.             lng = readvarinum();
  242.             lookfor = Mf_toberead - lng;
  243.             msginit();
  244.             msgadd(0xf0);
  245.  
  246.             while ( Mf_toberead > lookfor )
  247.                 msgadd(c=egetc());
  248.  
  249.             if ( c==0xf7 || Mf_nomerge==0 )
  250.                 sysex();
  251.             else
  252.                 sysexcontinue = 1;  /* merge into next msg */
  253.             break;
  254.  
  255.         case 0xf7:    /* sysex continuation or arbitrary stuff */
  256.  
  257.             /* watch out - Don't combine the next 2 statements */
  258.             lng = readvarinum();
  259.             lookfor = Mf_toberead - lng;
  260.  
  261.             if ( ! sysexcontinue )
  262.                 msginit();
  263.  
  264.             while ( Mf_toberead > lookfor )
  265.                 msgadd(c=egetc());
  266.  
  267.             if ( ! sysexcontinue ) {
  268.                 if ( Mf_arbitrary )
  269.                     (*Mf_arbitrary)(msgleng(),msg());
  270.             }
  271.             else if ( c == 0xf7 ) {
  272.                 sysex();
  273.                 sysexcontinue = 0;
  274.             }
  275.             break;
  276.         default:
  277.             badbyte(c);
  278.             break;
  279.         }
  280.     }
  281.     if ( Mf_endtrack )
  282.         (*Mf_endtrack)();
  283.     return;
  284. }
  285.  
  286. static VOID
  287. badbyte(c)
  288. int c;
  289. {
  290.     char buff[32];
  291.  
  292.     (VOID) sprintf(buff,"unexpected byte: 0x%02x",c);
  293.     mferror(buff);
  294. }
  295.  
  296. static VOID
  297. metaevent(type)
  298. {
  299.     int leng = msgleng();
  300.     char *m = msg();
  301.  
  302.     switch  ( type ) {
  303.     case 0x00:
  304.         if ( Mf_seqnum )
  305.             (*Mf_seqnum)(to16bit(m[0],m[1]));
  306.         break;
  307.     case 0x01:    /* Text event */
  308.     case 0x02:    /* Copyright notice */
  309.     case 0x03:    /* Sequence/Track name */
  310.     case 0x04:    /* Instrument name */
  311.     case 0x05:    /* Lyric */
  312.     case 0x06:    /* Marker */
  313.     case 0x07:    /* Cue point */
  314.     case 0x08:
  315.     case 0x09:
  316.     case 0x0a:
  317.     case 0x0b:
  318.     case 0x0c:
  319.     case 0x0d:
  320.     case 0x0e:
  321.     case 0x0f:
  322.         /* These are all text events */
  323.         if ( Mf_text )
  324.             ( Mf_text)(type,leng,m);
  325.         break;
  326.     case 0x2f:    /* End of Track */
  327.         if ( Mf_eot )
  328.             (*Mf_eot)();
  329.         break;
  330.     case 0x51:    /* Set tempo */
  331.         if ( Mf_tempo )
  332.             (*Mf_tempo)(to32bit(0,m[0],m[1],m[2]));
  333.         break;
  334.     case 0x54:
  335.         if ( Mf_smpte )
  336.             (*Mf_smpte)(m[0],m[1],m[2],m[3],m[4]);
  337.         break;
  338.     case 0x58:
  339.         if ( Mf_timesig )
  340.             (*Mf_timesig)(m[0],m[1],m[2],m[3]);
  341.         break;
  342.     case 0x59:
  343.         if ( Mf_keysig )
  344.             (*Mf_keysig)(m[0],m[1]);
  345.         break;
  346.     case 0x7f:
  347.         if ( Mf_sqspecific )
  348.             (*Mf_sqspecific)(leng,m);
  349.         break;
  350.     default:
  351.         if ( Mf_metamisc )
  352.             (*Mf_metamisc)(type,leng,m);
  353.     }
  354. }
  355.  
  356. static VOID
  357. sysex()
  358. {
  359.     if ( Mf_sysex )
  360.         (*Mf_sysex)(msgleng(),msg());
  361. }
  362.  
  363. static VOID chanmessage(status,c1,c2)
  364. int status;
  365. int c1, c2;
  366. {
  367.     int chan = status & 0xf;
  368.  
  369.     switch ( status & 0xf0 ) {
  370.     case NOTEOFF:
  371.         if ( Mf_off )
  372.             (*Mf_off)(chan,c1,c2);
  373.         break;
  374.     case NOTEON:
  375.         if ( Mf_on )
  376.             (*Mf_on)(chan,c1,c2);
  377.         break;
  378.     case PRESSURE:
  379.         if ( Mf_pressure )
  380.             (*Mf_pressure)(chan,c1,c2);
  381.         break;
  382.     case CONTROLLER:
  383.         if ( Mf_controller )
  384.             (*Mf_controller)(chan,c1,c2);
  385.         break;
  386.     case PITCHBEND:
  387.         if ( Mf_pitchbend )
  388.             (*Mf_pitchbend)(chan,c1,c2);
  389.         break;
  390.     case PROGRAM:
  391.         if ( Mf_program )
  392.             (*Mf_program)(chan,c1);
  393.         break;
  394.     case CHANPRESSURE:
  395.         if ( Mf_chanpressure )
  396.             (*Mf_chanpressure)(chan,c1);
  397.         break;
  398.     }
  399. }
  400.  
  401. /* readvarinum - read a varying-length number, and return the */
  402. /* number of characters it took. */
  403.  
  404. static long
  405. readvarinum()
  406. {
  407.     long value;
  408.     int c;
  409.  
  410.     c = egetc();
  411.     value = c;
  412.     if ( c & 0x80 ) {
  413.         value &= 0x7f;
  414.         do {
  415.             c = egetc();
  416.             value = (value << 7) + (c & 0x7f);
  417.         } while (c & 0x80);
  418.     }
  419.     return (value);
  420. }
  421.  
  422. static long
  423. to32bit(c1,c2,c3,c4)
  424. {
  425.     long value = 0L;
  426.  
  427.     value = (c1 & 0xff);
  428.     value = (value<<8) + (c2 & 0xff);
  429.     value = (value<<8) + (c3 & 0xff);
  430.     value = (value<<8) + (c4 & 0xff);
  431.     return (value);
  432. }
  433.  
  434. static
  435. to16bit(c1,c2)
  436. int c1, c2;
  437. {
  438.     return ((c1 & 0xff ) << 8) + (c2 & 0xff);
  439. }
  440.  
  441. static long
  442. read32bit()
  443. {
  444.     int c1, c2, c3, c4;
  445.  
  446.     c1 = egetc();
  447.     c2 = egetc();
  448.     c3 = egetc();
  449.     c4 = egetc();
  450.     return to32bit(c1,c2,c3,c4);
  451. }
  452.  
  453. static int
  454. read16bit()
  455. {
  456.     int c1, c2;
  457.     c1 = egetc();
  458.     c2 = egetc();
  459.     return to16bit(c1,c2);
  460. }
  461.  
  462. static VOID
  463. mferror(s)
  464. char *s;
  465. {
  466.     if ( Mf_error )
  467.         (*Mf_error)(s);
  468.     else
  469.         exit(1);
  470. }
  471.  
  472.  
  473.  
  474. /* The code below allows collection of a system exclusive message of */
  475. /* arbitrary length.  The Msgbuff is expanded as necessary.  The only */
  476. /* visible data/routines are msginit(), msgadd(), msg(), msgleng(). */
  477.  
  478. #define MSGINCREMENT 128
  479. static char *Msgbuff = 0;    /* message buffer */
  480. static int Msgsize = 0;        /* Size of currently allocated Msg */
  481. static int Msgindex = 0;    /* index of next available location in Msg */
  482.  
  483. static VOID
  484. msginit()
  485. {
  486.     Msgindex = 0;
  487. }
  488.  
  489. static char *
  490. msg()
  491. {
  492.     return(Msgbuff);
  493. }
  494.  
  495. static int
  496. msgleng()
  497. {
  498.     return(Msgindex);
  499. }
  500.  
  501. static VOID
  502. msgadd(c)
  503. int c;
  504. {
  505.     /* if necessary,relocate larger message buffer. */
  506.     if ( Msgindex >= Msgsize )
  507.         msgenlarge();
  508.     Msgbuff[Msgindex++] = c;
  509. }
  510.  
  511. static VOID
  512. msgenlarge()
  513. {
  514.     char *newmess;
  515.     char *oldmess = Msgbuff;
  516.     int oldleng = Msgsize;
  517.     char *malloc();
  518.  
  519.     Msgsize += MSGINCREMENT;
  520.     newmess = malloc( (unsigned)(sizeof(char)*Msgsize) );
  521.  
  522.     /* copy old message into larger new one */
  523.     if ( oldmess != 0 ) {
  524.         register char *p = newmess;
  525.         register char *q = oldmess;
  526.         register char *endq = &oldmess[oldleng];
  527.  
  528.         for ( ; q!=endq ; p++,q++ )
  529.             *p = *q;
  530.         free(oldmess);
  531.     }
  532.     Msgbuff = newmess;
  533. }
  534.  
  535.